﻿using System;
using JetBrains.Annotations;
using MugenMvvmToolkit.Annotations;
using MugenMvvmToolkit.Attributes;
using MugenMvvmToolkit.Interfaces;
using MugenMvvmToolkit.Interfaces.ViewModels;
using MugenMvvmToolkit.Models;

namespace MugenMvvmToolkit.ViewModels
{
    /// <summary>
    ///     Represents the default implementation of <see cref="IRelayCommand" />.
    /// </summary>
    public class RelayCommand<TArg> : RelayCommand
    {
        #region Constructors

        /// <summary>
        ///     Initializes a new instance of the <see cref="RelayCommand" /> class.
        /// </summary>
        /// <param name="execute">The specified command action for execute.</param>
        /// <param name="executionMode">
        ///     Specifies the execution mode for <c>RaiseCanExecuteChanged</c> method.
        /// </param>
        /// <param name="threadManager">
        ///     The specified <see cref="IThreadManager" />.
        /// </param>
        public RelayCommand([NotNull]Action<TArg> execute, ExecutionType? executionMode = null,
                            IThreadManager threadManager = null)
            : base(o => execute((TArg)o), executionMode, threadManager)
        {
            Should.NotBeNull(execute, "execute");
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="RelayCommand" /> class.
        /// </summary>
        /// <param name="execute">The specified command action for execute.</param>
        /// <param name="canExecute">The specified command condition.</param>
        /// <param name="notifiers">
        ///     The specified object implemented for auto call event CanExecuteChanged. If you change the properties of the objects to be caused by an event CanExecuteChanged.
        /// </param>
        public RelayCommand([NotNull]Action<TArg> execute, [NotNull] Predicate<TArg> canExecute, [NotEmptyParams] params object[] notifiers)
            : base(o => execute((TArg)o), o => canExecute((TArg)o), notifiers)
        {
            Should.NotBeNull(execute, "execute");
            Should.NotBeNull(canExecute, "canExecute");
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="RelayCommand" /> class.
        /// </summary>
        /// <param name="execute">The specified command action for execute.</param>
        /// <param name="canExecute">The specified command condition.</param>
        /// <param name="executionMode">
        ///     Specifies the execution mode for <c>RaiseCanExecuteChanged</c> method.
        /// </param>
        /// <param name="threadManager">
        ///     The specified <see cref="IThreadManager" />.
        /// </param>
        /// <param name="notifiers">
        ///     The specified object implemented for auto call event CanExecuteChanged. If you change the properties of the objects to be caused by an event CanExecuteChanged.
        /// </param>
        public RelayCommand([NotNull]Action<TArg> execute, [NotNull] Predicate<TArg> canExecute, ExecutionType? executionMode = null,
                            IThreadManager threadManager = null, [NotEmptyParams] params object[] notifiers)
            : base(o => execute((TArg)o), o => canExecute((TArg)o), executionMode, threadManager, notifiers)
        {
            Should.NotBeNull(execute, "execute");
            Should.NotBeNull(canExecute, "canExecute");
        }

        #endregion
    }
}